package com.yqg.education.controller;

import cn.hutool.core.io.FileUtil;
import com.aspose.words.*;
import com.yqg.education.common.Result;
import com.yqg.education.controller.dto.FileDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * 文件上传
 */
@RestController
@RequestMapping("/files")
@Api(tags = "文件管理")
@Slf4j
public class FilesController {

    @Value("${files.upload.path}")
    private String fileUploadPath;

    /**
     *文件上传接口
     * @param file 前端传过来的文件
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    @ApiOperation("文件上传接口")
    public String upload(@RequestParam MultipartFile file) throws IOException {
        log.info("上传文件：{}",file.getOriginalFilename() );
        //获取原始数据名
        String originalFilename = file.getOriginalFilename();
        //构造唯一的文件名（不能重复）
        assert originalFilename != null;
        int index = originalFilename.lastIndexOf(".");
        String extname = originalFilename.substring(index);//找到 . 的索引
        String fileName = originalFilename.substring(0,index);//分离 文件名
        String timestampStr = String.valueOf(System.currentTimeMillis());//当前时间戳
        String newFileName = fileName +timestampStr + extname;//原文件名加时间戳
        log.info("新文件名：{}", newFileName);
        //转存到本地
        String newPath = fileUploadPath + newFileName;//待修改
        File localFile = new File(newPath);
        File parentFile = localFile.getParentFile();
        if(!parentFile.exists()) {
            parentFile.mkdirs();
        }
        try {
            file.transferTo(new File(newPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return newPath;
    }

    /**
     * 文件下载接口   http://localhost:9096/file/{fileUUID}
     * @param fileUUID
     * @param response    1.在同一个网络下面 2.ping 对方IP 3.关闭防火墙
     * @throws IOException
     */
    @GetMapping("/download/{fileUUID}")
    @ApiOperation("文件下载接口")
    public void haikangDownload(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        //根据文件的唯一标识码获取文件
        File uploadFile = new File(fileUploadPath + fileUUID);
        //设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
        response.setContentType("application/octet-stream");

        //读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    @GetMapping("/codeDownload/{fileUUID}")
    @ApiOperation("二维码文件下载接口")
    public void codeDownload(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        //根据文件的唯一标识码获取文件
        File uploadFile = new File(fileUploadPath + fileUUID);
        //设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
        response.setContentType("application/octet-stream");

        //读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    /**
     * 文件上传(一个文件)
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/uploadSign")
    public Result uploadSign(MultipartFile file) throws Exception {
        log.info("上传文件：{}",file.getOriginalFilename() );
        //获取原始数据名
        String originalFilename = file.getOriginalFilename();
        //构造唯一的文件名（不能重复）
        assert originalFilename != null;
        int index = originalFilename.lastIndexOf(".");
        String extname = originalFilename.substring(index);//找到 . 的索引
        String fileName = originalFilename.substring(0,index);//分离 文件名
        String timestampStr = String.valueOf(System.currentTimeMillis());//当前时间戳
        String newFileName = fileName +timestampStr + extname;//原文件名加时间戳
        log.info("新文件名：{}", newFileName);
        //转存到本地
        String newPath = fileUploadPath + newFileName;//待修改
        File localFile = new File(newPath);
        File parentFile = localFile.getParentFile();
        if(!parentFile.exists()) {
            parentFile.mkdirs();
        }
        try {
            file.transferTo(new File(newPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        FileDTO fileDTO = new FileDTO();
        fileDTO.setName(fileName);
        fileDTO.setUrl("/api/file/download/" + newPath);
        return Result.success(fileDTO);
    }

    @GetMapping("/preview/{filename}")
    public ResponseEntity<byte[]> previewFile(@PathVariable String filename) {
        try {
            // 0. 初始化字体配置（每次请求执行）
            FontSettings.getDefaultInstance().setFontsFolder("/usr/share/fonts/chinese", true);

            // 1. 获取文件路径
            Path filePath = Paths.get(fileUploadPath).resolve(filename).normalize();
            if (!java.nio.file.Files.exists(filePath)) {
                return ResponseEntity.notFound().build();
            }

            // 2. 转换设置
            PdfSaveOptions options = new PdfSaveOptions();
            options.setFontEmbeddingMode(PdfFontEmbeddingMode.EMBED_ALL); // 强制嵌入所有字体


            // 3. 执行转换
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            Document doc = new Document(filePath.toString());
            doc.save(os, options);

            // 4. 返回结果
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_TYPE, "application/pdf")
                    .body(os.toByteArray());

        } catch (Exception e) {
            return ResponseEntity.internalServerError()
                    .body(("预览失败: " + e.getMessage()).getBytes(StandardCharsets.UTF_8)); // 明确编码
        }
    }
}
